Copied from upstream:
https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/271e3a5a53d9

# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# Date 1455014759 -7200
# Node ID 271e3a5a53d96871141e89271f611033b512e3e4
# Parent  9719b71d72dd2a3c5ee12ace156af2a63d9595ac
Bug 1228103. r=smaug. a=sylvestre

diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
--- a/parser/htmlparser/nsExpatDriver.cpp
+++ b/parser/htmlparser/nsExpatDriver.cpp
@@ -1127,22 +1127,28 @@ nsExpatDriver::ConsumeToken(nsScanner& a
       XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
 
       if (lastLineLength <= consumed) {
         // The length of the last line was less than what expat consumed, so
         // there was at least one line break in the consumed data. Store the
         // last line until the point where we stopped parsing.
         nsScannerIterator startLastLine = currentExpatPosition;
         startLastLine.advance(-((ptrdiff_t)lastLineLength));
-        CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine);
+        if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
+          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
+        }
       }
       else {
         // There was no line break in the consumed data, append the consumed
         // data.
-        AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
+        if (!AppendUnicodeTo(oldExpatPosition,
+                             currentExpatPosition,
+                             mLastLine)) {
+          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
+        }
       }
     }
 
     mExpatBuffered += length - consumed;
 
     if (BlockedOrInterrupted()) {
       PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
              ("Blocked or interrupted parser (probably for loading linked "
diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
--- a/parser/htmlparser/nsParser.cpp
+++ b/parser/htmlparser/nsParser.cpp
@@ -1508,17 +1508,19 @@ nsParser::ResumeParse(bool allowIteratio
                 DidBuildModel(mStreamStatus);
                 return NS_OK;
               }
             } else {
               CParserContext* theContext = PopContext();
               if (theContext) {
                 theIterationIsOk = allowIteration && theContextIsStringBased;
                 if (theContext->mCopyUnused) {
-                  theContext->mScanner->CopyUnusedData(mUnusedInput);
+                  if (!theContext->mScanner->CopyUnusedData(mUnusedInput)) {
+                    mInternalState = NS_ERROR_OUT_OF_MEMORY;
+                  }
                 }
 
                 delete theContext;
               }
 
               result = mInternalState;
               aIsFinalChunk = mParserContext &&
                               mParserContext->mStreamListenerState == eOnStop;
diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
--- a/parser/htmlparser/nsScanner.cpp
+++ b/parser/htmlparser/nsScanner.cpp
@@ -379,17 +379,19 @@ nsresult nsScanner::Peek(nsAString& aStr
   if (mCountRemaining < uint32_t(aNumChars + aOffset)) {
     end = mEndPosition;
   }
   else {
     end = start;
     end.advance(aNumChars);
   }
 
-  CopyUnicodeTo(start, end, aStr);
+  if (!CopyUnicodeTo(start, end, aStr)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   return NS_OK;
 }
 
 
 /**
  *  Skip whitespace on scanner input stream
  *  
@@ -542,17 +544,19 @@ nsresult nsScanner::ReadTagIdentifier(ns
 
     if (!found) {
       ++current;
     }
   }
 
   // Don't bother appending nothing.
   if (current != mCurrentPosition) {
-    AppendUnicodeTo(mCurrentPosition, current, aString);
+    if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
   }
 
   SetPosition(current);  
   if (current == end) {
     result = kEOF;
   }
 
   //DoErrTest(aString);
@@ -597,26 +601,30 @@ nsresult nsScanner::ReadEntityIdentifier
         default:
           found = ('a'<=theChar && theChar<='z') ||
                   ('A'<=theChar && theChar<='Z') ||
                   ('0'<=theChar && theChar<='9');
           break;
       }
 
       if(!found) {
-        AppendUnicodeTo(mCurrentPosition, current, aString);
+        if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
+          return NS_ERROR_OUT_OF_MEMORY;
+        }
         break;
       }
     }
     ++current;
   }
   
   SetPosition(current);
   if (current == end) {
-    AppendUnicodeTo(origin, current, aString);
+    if (!AppendUnicodeTo(origin, current, aString)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     return kEOF;
   }
 
   //DoErrTest(aString);
 
   return result;
 }
 
@@ -646,26 +654,30 @@ nsresult nsScanner::ReadNumber(nsString&
   while(current != end) {
     theChar=*current;
     if(theChar) {
       done = (theChar < '0' || theChar > '9') && 
              ((aBase == 16)? (theChar < 'A' || theChar > 'F') &&
                              (theChar < 'a' || theChar > 'f')
                              :true);
       if(done) {
-        AppendUnicodeTo(origin, current, aString);
+        if (!AppendUnicodeTo(origin, current, aString)) {
+          return NS_ERROR_OUT_OF_MEMORY;
+        }
         break;
       }
     }
     ++current;
   }
 
   SetPosition(current);
   if (current == end) {
-    AppendUnicodeTo(origin, current, aString);
+    if (!AppendUnicodeTo(origin, current, aString)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     return kEOF;
   }
 
   //DoErrTest(aString);
 
   return result;
 }
 
@@ -712,37 +724,43 @@ nsresult nsScanner::ReadWhitespace(nsSca
           char16_t thePrevChar = theChar;
           theChar = (++current != end) ? *current : '\0';
           if ((thePrevChar == '\r' && theChar == '\n') ||
               (thePrevChar == '\n' && theChar == '\r')) {
             theChar = (++current != end) ? *current : '\0'; // CRLF == LFCR => LF
             haveCR = true;
           } else if (thePrevChar == '\r') {
             // Lone CR becomes CRLF; callers should know to remove extra CRs
-            AppendUnicodeTo(origin, current, aString);
+            if (!AppendUnicodeTo(origin, current, aString)) {
+              return NS_ERROR_OUT_OF_MEMORY;
+            }
             aString.writable().Append(char16_t('\n'));
             origin = current;
             haveCR = true;
           }
         }
         break;
       case ' ' :
       case '\t':
         theChar = (++current != end) ? *current : '\0';
         break;
       default:
         done = true;
-        AppendUnicodeTo(origin, current, aString);
+        if (!AppendUnicodeTo(origin, current, aString)) {
+          return NS_ERROR_OUT_OF_MEMORY;
+        }
         break;
     }
   }
 
   SetPosition(current);
   if (current == end) {
-    AppendUnicodeTo(origin, current, aString);
+    if (!AppendUnicodeTo(origin, current, aString)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
     result = kEOF;
   }
 
   aHaveCR = haveCR;
   return result;
 }
 
 //XXXbz callers of this have to manage their lone '\r' themselves if they want
@@ -846,34 +864,38 @@ nsresult nsScanner::ReadUntil(nsAString&
     if(!(theChar & aEndCondition.mFilter)) {
       // They were. Do a thorough check.
 
       setcurrent = setstart;
       while (*setcurrent) {
         if (*setcurrent == theChar) {
           if(addTerminal)
             ++current;
-          AppendUnicodeTo(origin, current, aString);
+          if (!AppendUnicodeTo(origin, current, aString)) {
+            return NS_ERROR_OUT_OF_MEMORY;
+          }
           SetPosition(current);
 
           //DoErrTest(aString);
 
           return NS_OK;
         }
         ++setcurrent;
       }
     }
     
     ++current;
   }
 
   // If we are here, we didn't find any terminator in the string and
   // current = mEndPosition
   SetPosition(current);
-  AppendUnicodeTo(origin, current, aString);
+  if (!AppendUnicodeTo(origin, current, aString)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   return kEOF;
 }
 
 nsresult nsScanner::ReadUntil(nsScannerSharedSubstring& aString,
                               const nsReadEndCondition& aEndCondition,
                               bool addTerminal)
 {  
   if (!mSlidingBuffer) {
@@ -906,34 +928,38 @@ nsresult nsScanner::ReadUntil(nsScannerS
     if(!(theChar & aEndCondition.mFilter)) {
       // They were. Do a thorough check.
 
       setcurrent = setstart;
       while (*setcurrent) {
         if (*setcurrent == theChar) {
           if(addTerminal)
             ++current;
-          AppendUnicodeTo(origin, current, aString);
+          if (!AppendUnicodeTo(origin, current, aString)) {
+            return NS_ERROR_OUT_OF_MEMORY;
+          }
           SetPosition(current);
 
           //DoErrTest(aString);
 
           return NS_OK;
         }
         ++setcurrent;
       }
     }
     
     ++current;
   }
 
   // If we are here, we didn't find any terminator in the string and
   // current = mEndPosition
   SetPosition(current);
-  AppendUnicodeTo(origin, current, aString);
+  if (!AppendUnicodeTo(origin, current, aString)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   return kEOF;
 }
 
 nsresult nsScanner::ReadUntil(nsScannerIterator& aStart, 
                               nsScannerIterator& aEnd,
                               const nsReadEndCondition &aEndCondition,
                               bool addTerminal)
 {
@@ -1025,26 +1051,30 @@ nsresult nsScanner::ReadUntil(nsAString&
     if (theChar == '\0') {
       ReplaceCharacter(current, sInvalid);
       theChar = sInvalid;
     }
 
     if (aTerminalChar == theChar) {
       if(addTerminal)
         ++current;
-      AppendUnicodeTo(origin, current, aString);
+      if (!AppendUnicodeTo(origin, current, aString)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
       SetPosition(current);
       return NS_OK;
     }
     ++current;
   }
 
   // If we are here, we didn't find any terminator in the string and
   // current = mEndPosition
-  AppendUnicodeTo(origin, current, aString);
+  if (!AppendUnicodeTo(origin, current, aString)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   SetPosition(current);
   return kEOF;
 
 }
 
 void nsScanner::BindSubstring(nsScannerSubstring& aSubstring, const nsScannerIterator& aStart, const nsScannerIterator& aEnd)
 {
   aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd);
@@ -1142,29 +1172,29 @@ bool nsScanner::AppendToBuffer(nsScanner
 }
 
 /**
  *  call this to copy bytes out of the scanner that have not yet been consumed
  *  by the tokenization process.
  *  
  *  @update  gess 5/12/98
  *  @param   aCopyBuffer is where the scanner buffer will be copied to
- *  @return  nada
+ *  @return  true if OK or false on OOM
  */
-void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
+bool nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
   if (!mSlidingBuffer) {
     aCopyBuffer.Truncate();
-    return;
+    return true;
   }
 
   nsScannerIterator start, end;
   start = mCurrentPosition;
   end = mEndPosition;
 
-  CopyUnicodeTo(start, end, aCopyBuffer);
+  return CopyUnicodeTo(start, end, aCopyBuffer);
 }
 
 /**
  *  Retrieve the name of the file that the scanner is reading from.
  *  In some cases, it's just a given name, because the scanner isn't
  *  really reading from a file.
  *  
  *  @update  gess 5/12/98
diff --git a/parser/htmlparser/nsScanner.h b/parser/htmlparser/nsScanner.h
--- a/parser/htmlparser/nsScanner.h
+++ b/parser/htmlparser/nsScanner.h
@@ -204,19 +204,19 @@ class nsScanner {
                       nsIRequest *aRequest);
 
       /**
        *  Call this to copy bytes out of the scanner that have not yet been consumed
        *  by the tokenization process.
        *  
        *  @update  gess 5/12/98
        *  @param   aCopyBuffer is where the scanner buffer will be copied to
-       *  @return  nada
+       *  @return  true if OK or false on OOM
        */
-      void CopyUnusedData(nsString& aCopyBuffer);
+      bool CopyUnusedData(nsString& aCopyBuffer);
 
       /**
        *  Retrieve the name of the file that the scanner is reading from.
        *  In some cases, it's just a given name, because the scanner isn't
        *  really reading from a file.
        *  
        *  @update  gess 5/12/98
        *  @return  
diff --git a/parser/htmlparser/nsScannerString.cpp b/parser/htmlparser/nsScannerString.cpp
--- a/parser/htmlparser/nsScannerString.cpp
+++ b/parser/htmlparser/nsScannerString.cpp
@@ -461,61 +461,63 @@ copy_multifragment_string( nsScannerIter
         sink_traits::write(result, source_traits::read(first), distance);
         NS_ASSERTION(distance > 0, "|copy_multifragment_string| will never terminate");
         source_traits::advance(first, distance);
       }
 
     return result;
   }
 
-void
+bool
 CopyUnicodeTo( const nsScannerIterator& aSrcStart,
                const nsScannerIterator& aSrcEnd,
                nsAString& aDest )
   {
     nsAString::iterator writer;
     if (!aDest.SetLength(Distance(aSrcStart, aSrcEnd), mozilla::fallible)) {
       aDest.Truncate();
-      return; // out of memory
+      return false; // out of memory
     }
     aDest.BeginWriting(writer);
     nsScannerIterator fromBegin(aSrcStart);
     
     copy_multifragment_string(fromBegin, aSrcEnd, writer);
+    return true;
   }
 
-void
+bool
 AppendUnicodeTo( const nsScannerIterator& aSrcStart,
                  const nsScannerIterator& aSrcEnd,
                  nsScannerSharedSubstring& aDest )
   {
     // Check whether we can just create a dependent string.
     if (aDest.str().IsEmpty()) {
       // We can just make |aDest| point to the buffer.
       // This will take care of copying if the buffer spans fragments.
       aDest.Rebind(aSrcStart, aSrcEnd);
-    } else {
-      // The dest string is not empty, so it can't be a dependent substring.
-      AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
+      return true;
     }
+    // The dest string is not empty, so it can't be a dependent substring.
+    return AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
   }
 
-void
+bool
 AppendUnicodeTo( const nsScannerIterator& aSrcStart,
                  const nsScannerIterator& aSrcEnd,
                  nsAString& aDest )
   {
     nsAString::iterator writer;
     uint32_t oldLength = aDest.Length();
     if (!aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd), mozilla::fallible))
-      return; // out of memory
+      return false; // out of memory
     aDest.BeginWriting(writer).advance(oldLength);
     nsScannerIterator fromBegin(aSrcStart);
     
     copy_multifragment_string(fromBegin, aSrcEnd, writer);
+    return true;
   }
 
 bool
 FindCharInReadable( char16_t aChar,
                     nsScannerIterator& aSearchStart,
                     const nsScannerIterator& aSearchEnd )
   {
     while ( aSearchStart != aSearchEnd )
diff --git a/parser/htmlparser/nsScannerString.h b/parser/htmlparser/nsScannerString.h
--- a/parser/htmlparser/nsScannerString.h
+++ b/parser/htmlparser/nsScannerString.h
@@ -539,43 +539,43 @@ nsScannerBufferList::Position::operator=
 inline
 size_t
 Distance( const nsScannerIterator& aStart, const nsScannerIterator& aEnd )
   {
     typedef nsScannerBufferList::Position Position;
     return Position::Distance(Position(aStart), Position(aEnd));
   }
 
-void
+bool
 CopyUnicodeTo( const nsScannerIterator& aSrcStart,
                const nsScannerIterator& aSrcEnd,
                nsAString& aDest );
 
 inline
-void
+bool
 CopyUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
   {
     nsScannerIterator begin, end;
-    CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+    return CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
   }
 
-void
+bool
 AppendUnicodeTo( const nsScannerIterator& aSrcStart,
                  const nsScannerIterator& aSrcEnd,
                  nsAString& aDest );
 
 inline
-void
+bool
 AppendUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
   {
     nsScannerIterator begin, end;
-    AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+    return AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
   }
 
-void
+bool
 AppendUnicodeTo( const nsScannerIterator& aSrcStart,
                  const nsScannerIterator& aSrcEnd,
                  nsScannerSharedSubstring& aDest );
 
 bool
 FindCharInReadable( char16_t aChar,
                     nsScannerIterator& aStart,
                     const nsScannerIterator& aEnd );

